<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="xzJwL" id="xzJwL"><span data-lake-id="ua13b40f6" id="ua13b40f6">典型回答</span></h1>
  <p data-lake-id="u47392152" id="u47392152"><span data-lake-id="ub43924de" id="ub43924de">数据库的行级锁根据锁的粒度不同，可以叫做不同的名字。</span></p>
  <p data-lake-id="u5769f256" id="u5769f256"><span data-lake-id="u4fbde67c" id="u4fbde67c">​</span><br></p>
  <p data-lake-id="u1d0bce30" id="u1d0bce30"><span data-lake-id="u1e768caf" id="u1e768caf">Record Lock表示记录锁，锁的是索引记录。 </span></p>
  <p data-lake-id="u2d8b3468" id="u2d8b3468"><span data-lake-id="u6a3350b8" id="u6a3350b8">​</span><br></p>
  <p data-lake-id="ubdbfc70f" id="ubdbfc70f"><span data-lake-id="u1c2e9619" id="u1c2e9619">Gap Lock是间隙锁，锁的是索引记录之间的间隙。 </span></p>
  <p data-lake-id="u96a1df8c" id="u96a1df8c"><span data-lake-id="u6e85a180" id="u6e85a180">​</span><br></p>
  <p data-lake-id="u81c82659" id="u81c82659"><span data-lake-id="u60c5f793" id="u60c5f793">Next-Key Lock是Record Lock和Gap Lock的组合，同时锁索引记录和间隙。他的范围是左开右闭的。</span></p>
  <p data-lake-id="u3ed27a5f" id="u3ed27a5f"><span data-lake-id="u26ef6287" id="u26ef6287">​</span><br></p>
  <h1 data-lake-id="vmgsX" id="vmgsX"><span data-lake-id="uc6462e21" id="uc6462e21">扩展知识</span></h1>
  <h2 data-lake-id="rSNos" id="rSNos"><span data-lake-id="u45b7924e" id="u45b7924e">Record Lock</span></h2>
  <p data-lake-id="u19021dd3" id="u19021dd3"><br></p>
  <p data-lake-id="u8184f613" id="u8184f613"><strong><span data-lake-id="u9211a4de" id="u9211a4de">Record Lock，翻译成记录锁，是加在索引记录上的锁。</span></strong><span data-lake-id="u27ccaaeb" id="u27ccaaeb">例如，</span><code data-lake-id="ua1176147" id="ua1176147"><span data-lake-id="u97f17eeb" id="u97f17eeb">SELECT c1 FROM t WHERE c1 = 10 For UPDATE;</span></code><span data-lake-id="u8832812e" id="u8832812e">会对c1=10这条记录加锁，为了防止任何其他事务插入、更新或删除c1值为10的行。</span></p>
  <p data-lake-id="u67dbbce9" id="u67dbbce9"><br></p>
  <p data-lake-id="uaef2777c" id="uaef2777c"><img src="http://www.hollischuang.com/wp-content/uploads/2022/03/16313419014489.jpg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"><span data-lake-id="u922a115c" id="u922a115c">​</span></p>
  <p data-lake-id="u71ecf7e7" id="u71ecf7e7"><br></p>
  <p data-lake-id="u13159b52" id="u13159b52"><span data-lake-id="u556fa57e" id="u556fa57e">需要特别注意的是，</span><strong><span data-lake-id="u266bd11e" id="u266bd11e">记录锁锁定的是索引记录</span></strong><span data-lake-id="u7eb441ae" id="u7eb441ae">。即使表没有定义索引，InnoDB也会创建一个隐藏的聚集索引，并使用这个索引来锁定记录。</span></p>
  <p data-lake-id="uc9263aff" id="uc9263aff"><br></p>
  <h2 data-lake-id="SjJJZ" id="SjJJZ"><span data-lake-id="u783ddfc9" id="u783ddfc9">Gap Lock</span></h2>
  <p data-lake-id="ued895da5" id="ued895da5"><br></p>
  <p data-lake-id="uc7688e07" id="uc7688e07"><strong><span data-lake-id="uf2ddaa59" id="uf2ddaa59">Gap Lock，翻译成间隙锁，他指的是在索引记录之间的间隙上的锁</span></strong><span data-lake-id="u368fcb03" id="u368fcb03">，或者在第一个索引记录之前或最后一个索引记录之后的间隙上的锁。</span></p>
  <p data-lake-id="u740eba7e" id="u740eba7e"><br></p>
  <p data-lake-id="u29d3f58f" id="u29d3f58f"><span data-lake-id="u6411ce24" id="u6411ce24">那么，这里所谓的Gap（间隙）又怎么理解呢？</span></p>
  <p data-lake-id="ube7047f0" id="ube7047f0"><br></p>
  <p data-lake-id="ud500b5b0" id="ud500b5b0"><strong><span data-lake-id="u03398e6c" id="u03398e6c">Gap指的是InnoDB的索引数据结构中可以插入新值的位置。</span></strong></p>
  <p data-lake-id="uabe45af9" id="uabe45af9"><br></p>
  <p data-lake-id="ue7a57540" id="ue7a57540"><span data-lake-id="u5add8729" id="u5add8729">当你用语句SELECT…FOR UPDATE锁定一组行时。InnoDB可以创建锁，应用于索引中的实际值以及他们之间的间隙。例如，如果选择所有大于10的值进行更新，间隙锁将阻止另一个事务插入大于10的新值。</span></p>
  <p data-lake-id="ufa0d2cdf" id="ufa0d2cdf"><br></p>
  <p data-lake-id="u23456569" id="u23456569"><img src="http://www.hollischuang.com/wp-content/uploads/2022/03/16313418798174.jpg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u31ac58da" id="u31ac58da" style="text-align: center"><span data-lake-id="uc6778960" id="uc6778960">（实际会锁到+∞，这里为了演示什么是gap简化了一下）</span></p>
  <p data-lake-id="u2940faee" id="u2940faee"><br></p>
  <p data-lake-id="u6a57ad06" id="u6a57ad06"><strong><span data-lake-id="uef10aaff" id="uef10aaff">既然是锁，那么就可能会影响到数据库的并发性</span></strong><span data-lake-id="ud3e7ede4" id="ud3e7ede4">，所以，间隙锁只有在Repeatable Reads这种隔离级别中才会起作用。</span></p>
  <p data-lake-id="ud911b4a0" id="ud911b4a0"><br></p>
  <p data-lake-id="uab16fd99" id="uab16fd99"><span data-lake-id="ubc2cff52" id="ubc2cff52">在Repeatable Reads这种隔离下，对于锁定的读操作（select ... for update 、 lock in share mode)、update操作、delete操作时，会进行如下的加锁：</span></p>
  <p data-lake-id="ucbdab134" id="ucbdab134"><br></p>
  <ul list="ua621ee5e">
   <li fid="u2b2d07c0" data-lake-id="u8387458a" id="u8387458a"><span data-lake-id="udfde3066" id="udfde3066"> 对于具有唯一搜索条件的唯一索引，InnoDB只锁定找到的索引记录，而不会锁定间隙。 </span></li>
   <li fid="u2b2d07c0" data-lake-id="u2af84820" id="u2af84820"><span data-lake-id="u860671e5" id="u860671e5"> 对于其他搜索条件，InnoDB锁定扫描的索引范围，使用gap lock或next-key lock来阻塞其他事务插入范围覆盖的间隙。 </span></li>
  </ul>
  <p data-lake-id="u92ead2bb" id="u92ead2bb"><br></p>
  <p data-lake-id="ud800b32d" id="ud800b32d"><strong><span data-lake-id="u7ee4a246" id="u7ee4a246">也就是说，对于SELECT FOR UPDATE、LOCK IN SHARE MODE、UPDATE和DELETE等语句处理时，除了对唯一索引的唯一搜索外都会获取gap锁或next-key锁，即锁住其扫描的范围。</span></strong></p>
  <p data-lake-id="u9e5706d9" id="u9e5706d9"><br></p>
  <h2 data-lake-id="obA3s" id="obA3s"><span data-lake-id="u5a1a62ae" id="u5a1a62ae">Next-Key Lock</span></h2>
  <p data-lake-id="u5f75ce01" id="u5f75ce01"><br></p>
  <p data-lake-id="u98c42966" id="u98c42966"><span data-lake-id="u2b1603ad" id="u2b1603ad">Next-Key锁是索引记录上的记录锁和索引记录之前间隙上的间隙锁的组合。</span></p>
  <p data-lake-id="u40e34800" id="u40e34800"><br></p>
  <p data-lake-id="uc578aed8" id="uc578aed8"><img src="http://www.hollischuang.com/wp-content/uploads/2022/03/16313418544575.jpg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"><span data-lake-id="uf74570e1" id="uf74570e1">​</span></p>
  <p data-lake-id="u9f21bc08" id="u9f21bc08"><br></p>
  <p data-lake-id="uba9b8a47" id="uba9b8a47"><span data-lake-id="ub1d92286" id="ub1d92286">假设一个索引包含值10、11、13和20。此索引可能的next-key锁包括以下区间:</span></p>
  <p data-lake-id="u322b7ac5" id="u322b7ac5"><br></p>
  <pre lang="java"><code>
(-∞, 10]
(10, 11]
(11, 13]
(13, 20]
(20, ∞ ]
</code></pre>
  <p data-lake-id="ud1172eff" id="ud1172eff"><br></p>
  <p data-lake-id="u2e872719" id="u2e872719"><span data-lake-id="u258ba56b" id="u258ba56b">对于最后一个间隙，∞不是一个真正的索引记录，因此，实际上，这个next-key锁只锁定最大索引值之后的间隙。</span></p>
  <p data-lake-id="u446701a2" id="u446701a2"><br></p>
  <p data-lake-id="u30f725f8" id="u30f725f8"><span data-lake-id="u035e1e2d" id="u035e1e2d">所以，Next-Key 的锁的范围都是左开右闭的。</span></p>
  <p data-lake-id="u5f2cda43" id="u5f2cda43"><br></p>
  <p data-lake-id="u858ab289" id="u858ab289"><span data-lake-id="uccd79e1a" id="uccd79e1a">Next-Key Lock和Gap Lock一样，只有在InnoDB的RR隔离级别中才会生效。</span></p>
  <p data-lake-id="ub776ed4c" id="ub776ed4c"><br></p>
  <h2 data-lake-id="ktcV3" id="ktcV3"><span data-lake-id="u0a1974be" id="u0a1974be">MySQL的加锁原则</span></h2>
  <p data-lake-id="ud9d04485" id="ud9d04485"><br></p>
  <p data-lake-id="ucde1d37f" id="ucde1d37f"><span data-lake-id="ub5bc21d8" id="ub5bc21d8">前面介绍过了Record Lock、Gap Lock和Next-Key Lock，但是并没有说明加锁规则。关于加锁规则，我是看了丁奇大佬的《MySQL实战45讲》中的文章之后理解的，他总结的加锁规则里面，包含了两个“原则”、两个“优化”和一个“bug”：</span></p>
  <p data-lake-id="ud327bff1" id="ud327bff1"><br></p>
  <p data-lake-id="ucfc5b81d" id="ucfc5b81d"><span data-lake-id="udd6665a0" id="udd6665a0">原则 1：加锁的基本单位是 next-key lock。是一个前开后闭区间。 </span></p>
  <p data-lake-id="ued0d40f0" id="ued0d40f0"><span data-lake-id="u224fb0e9" id="u224fb0e9">原则 2：查找过程中访问到的对象才会加锁。 </span></p>
  <p data-lake-id="u59701b99" id="u59701b99"><span data-lake-id="u50ba8a27" id="u50ba8a27">优化 1：索引上的等值查询，给唯一索引加锁的时候，next-key lock 退化为行锁。 </span></p>
  <p data-lake-id="u471d72c1" id="u471d72c1"><span data-lake-id="ue3c3e7f3" id="ue3c3e7f3">优化 2：索引上的等值查询，向右遍历时且最后一个值不满足等值条件的时候，next-key lock 退化为间隙锁。 </span></p>
  <p data-lake-id="uead40091" id="uead40091"><span data-lake-id="u9f841670" id="u9f841670">一个 bug：唯一索引上的范围查询会访问到不满足条件的第一个值为止。</span></p>
  <p data-lake-id="u8c3b441c" id="u8c3b441c"><br></p>
  <p data-lake-id="uf8012461" id="uf8012461"><span data-lake-id="ued236c5d" id="ued236c5d">假如，数据库表中当前有以下记录：</span></p>
  <p data-lake-id="u2af892f5" id="u2af892f5"><br></p>
  <p data-lake-id="u7a08270d" id="u7a08270d"><img src="http://www.hollischuang.com/wp-content/uploads/2022/03/16313425680103.jpg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_29%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"><span data-lake-id="ue3210039" id="ue3210039">​</span></p>
  <p data-lake-id="uddad0e0f" id="uddad0e0f"><br></p>
  <p data-lake-id="u57157951" id="u57157951"><span data-lake-id="u6c5efabb" id="u6c5efabb">当我们执行</span><code data-lake-id="u4bc81069" id="u4bc81069"><span data-lake-id="u4b628a58" id="u4b628a58">update t set d=d+1 where id = 7</span></code><span data-lake-id="uf35ed736" id="uf35ed736">的时候，由于表 t 中没有 id=7 的记录，所以：</span></p>
  <p data-lake-id="u7d842812" id="u7d842812"><br></p>
  <ul list="udbc1b565">
   <li fid="u9b9a61d3" data-lake-id="u13bfffb7" id="u13bfffb7"><span data-lake-id="uecfe5c79" id="uecfe5c79">根据原则 1，加锁单位是 next-key lock，session A 加锁范围就是 (5,10]；</span></li>
   <li fid="u9b9a61d3" data-lake-id="ua0f000dc" id="ua0f000dc"><span data-lake-id="u129f624e" id="u129f624e">根据优化 2，这是一个等值查询 (id=7)，而 id=10 不满足查询条件，next-key lock 退化成间隙锁，因此最终加锁的范围是 (5,10)。</span></li>
  </ul>
  <p data-lake-id="ud43a9ec1" id="ud43a9ec1"><br></p>
  <p data-lake-id="uace263ba" id="uace263ba"><span data-lake-id="ua806cf28" id="ua806cf28">当我们执行</span><code data-lake-id="u60c99d00" id="u60c99d00"><span data-lake-id="ufa350bd4" id="ufa350bd4">select * from t where id&gt;=10 and id&lt;11 for update</span></code><span data-lake-id="u6d7aa4f1" id="u6d7aa4f1">的时候：</span></p>
  <p data-lake-id="u4d6a8910" id="u4d6a8910"><br></p>
  <ul list="u351ce202">
   <li fid="u0b9a539b" data-lake-id="u60e9ab08" id="u60e9ab08"><span data-lake-id="ube4e6179" id="ube4e6179">根据原则 1，加锁单位是 next-key lock，会给 (5,10]加上 next-key lock，范围查找就往后继续找，找到 id=15 这一行停下来</span></li>
   <li fid="u0b9a539b" data-lake-id="ua591c589" id="ua591c589"><span data-lake-id="u6517f712" id="u6517f712">根据优化 1，主键 id 上的等值条件，退化成行锁，只加了 id=10 这一行的行锁。</span></li>
   <li fid="u0b9a539b" data-lake-id="ubfd8819c" id="ubfd8819c"><span data-lake-id="u6552640e" id="u6552640e">根据原则 2，访问到的都要加锁，因此需要加 next-key lock(10,15]。因此最终加的是行锁 id=10 和 next-key lock(10,15]。</span></li>
  </ul>
  <p data-lake-id="u13a425b3" id="u13a425b3"><br></p>
  <p data-lake-id="u8708e9d6" id="u8708e9d6"><span data-lake-id="ueea3684f" id="ueea3684f">当我们执行</span><code data-lake-id="u0c38bbfa" id="u0c38bbfa"><span data-lake-id="u11be0eb0" id="u11be0eb0">select * from t where id&gt;10 and id&lt;=15 for update</span></code><span data-lake-id="u3c766e14" id="u3c766e14">的时候： </span><em><span data-lake-id="u6a01a58e" id="u6a01a58e"> </span></em></p>
  <p data-lake-id="uacdd9950" id="uacdd9950"><em><span data-lake-id="uc7eb9a5d" id="uc7eb9a5d">​</span></em><br></p>
  <p data-lake-id="u39a4a4ee" id="u39a4a4ee"><em><span data-lake-id="u873086d4" id="u873086d4">根据原则 1，加锁单位是 next-key lock，会给 (10,15]加上 next-key lock，并且因为 id 是唯一键，所以循环判断到 id=15 这一行就应该停止了。 </span></em><span data-lake-id="u8cc81fad" id="u8cc81fad"> </span></p>
  <p data-lake-id="u5bd45629" id="u5bd45629"><span data-lake-id="ufc65656f" id="ufc65656f">但是，InnoDB 会往前扫描到第一个不满足条件的行为止，也就是 id=20。而且由于这是个范围扫描，因此索引 id 上的 (15,20]这个 next-key lock 也会被锁上。</span></p>
  <p data-lake-id="u724a71f7" id="u724a71f7"><br></p>
  <p data-lake-id="ua72005dc" id="ua72005dc"><span data-lake-id="u87b91d42" id="u87b91d42">假如，数据库表中当前有以下记录：</span></p>
  <p data-lake-id="uc2584943" id="uc2584943"><br></p>
  <p data-lake-id="u220e86ab" id="u220e86ab"><img src="http://www.hollischuang.com/wp-content/uploads/2022/03/16313428606603.jpg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_29%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"><span data-lake-id="u52a35272" id="u52a35272">​</span></p>
  <p data-lake-id="uefd7b8ee" id="uefd7b8ee"><br></p>
  <p data-lake-id="u25c432a1" id="u25c432a1"><span data-lake-id="u6424fc99" id="u6424fc99">当我们执行</span><code data-lake-id="uf3cabd99" id="uf3cabd99"><span data-lake-id="u67cee05a" id="u67cee05a">select id from t where c=5 lock in share mode</span></code><span data-lake-id="u0d0e19bb" id="u0d0e19bb">的时候：</span></p>
  <p data-lake-id="u5b2a8746" id="u5b2a8746"><br></p>
  <ul list="u453cb08a">
   <li fid="u481624f8" data-lake-id="u72cc03d1" id="u72cc03d1"><span data-lake-id="u657d7f49" id="u657d7f49">根据原则 1，加锁单位是 next-key lock，因此会给 (0,5]加上 next-key lock。要注意 c 是普通索引，因此仅访问 c=5 这一条记录是不能马上停下来的，需要向右遍历，查到 c=10 才放弃。</span></li>
   <li fid="u481624f8" data-lake-id="u211e4826" id="u211e4826"><span data-lake-id="uf05fe114" id="uf05fe114">根据原则 2，访问到的都要加锁，因此要给 (5,10]加 next-key lock。</span></li>
   <li fid="u481624f8" data-lake-id="u8ebcae54" id="u8ebcae54"><span data-lake-id="u5dfc1d1a" id="u5dfc1d1a">根据优化 2：等值判断，向右遍历，最后一个值不满足 c=5 这个等值条件，因此退化成间隙锁 (5,10)。</span></li>
   <li fid="u481624f8" data-lake-id="ua7165220" id="ua7165220"><span data-lake-id="u29aed9e1" id="u29aed9e1">根据原则 2 ，只有访问到的对象才会加锁，这个查询使用覆盖索引，并不需要访问主键索引，所以主键索引上没有加任何锁。</span></li>
  </ul>
  <p data-lake-id="u0d7ce143" id="u0d7ce143"><br></p>
  <p data-lake-id="u83c66928" id="u83c66928"><span data-lake-id="u16dfa86c" id="u16dfa86c">当我们执行</span><code data-lake-id="u77808d3b" id="u77808d3b"><span data-lake-id="u7c5667fb" id="u7c5667fb">select * from t where c&gt;=10 and c&lt;11 for update</span></code><span data-lake-id="u0ccb0f0f" id="u0ccb0f0f">的时候：</span></p>
  <p data-lake-id="u006f6b39" id="u006f6b39"><br></p>
  <ul list="u73b89895">
   <li fid="u91ce4a63" data-lake-id="ub502c5a4" id="ub502c5a4"><span data-lake-id="u739906e8" id="u739906e8">根据原则 1，加锁单位是 next-key lock，会给 (5,10]加上 next-key lock，范围查找就往后继续找，找到 id=15 这一行停下来</span></li>
   <li fid="u91ce4a63" data-lake-id="uea3291d9" id="uea3291d9"><span data-lake-id="u6b36d644" id="u6b36d644">根据原则 2，访问到的都要加锁，因此需要加 next-key lock(10,15]。</span></li>
   <li fid="u91ce4a63" data-lake-id="ufe22759f" id="ufe22759f"><span data-lake-id="ue6f154d4" id="ue6f154d4">由于索引 c 是非唯一索引，没有优化规则，也就是说不会蜕变为行锁，因此最终 sesion A 加的锁是，索引 c 上的 (5,10] 和 (10,15] 这两个 next-key lock。</span></li>
  </ul>
  <p data-lake-id="u8c291226" id="u8c291226"><br></p>
  <h2 data-lake-id="rcRMz" id="rcRMz"><span data-lake-id="u86dfe69e" id="u86dfe69e">总结</span></h2>
  <p data-lake-id="u31a5ad24" id="u31a5ad24"><br></p>
  <p data-lake-id="u2f5dfb5a" id="u2f5dfb5a"><span data-lake-id="ub38bae65" id="ub38bae65">以上，我们介绍了InnoDB中的锁机制，一共有三种锁，分别是Record Lock、Gap Lock和Next-Key Lock。</span></p>
  <p data-lake-id="ue4d3a04f" id="ue4d3a04f"><br></p>
  <p data-lake-id="u4a37a879" id="u4a37a879"><span data-lake-id="u513e799b" id="u513e799b">Record Lock表示记录锁，锁的是索引记录。 Gap Lock是间隙锁，说的是索引记录之间的间隙。 Next-Key Lock是Record Lock和Gap Lock的组合，同时锁索引记录和间隙。他的范围是左开右闭的。</span></p>
  <p data-lake-id="u83de1184" id="u83de1184"><br></p>
  <p data-lake-id="uadac5152" id="uadac5152"><span data-lake-id="uc87aaaa9" id="uc87aaaa9">InnoDB的RR级别中，加锁的基本单位是 next-key lock，只要扫描到的数据都会加锁。唯一索引上的范围查询会访问到不满足条件的第一个值为止。</span></p>
  <p data-lake-id="u36b50b40" id="u36b50b40"><br></p>
  <p data-lake-id="u93f018dc" id="u93f018dc"><span data-lake-id="u6b15b820" id="u6b15b820">同时，为了提升性能和并发度，也有两个优化点：</span></p>
  <p data-lake-id="u942c436c" id="u942c436c"><br></p>
  <ul list="u070c1eb6">
   <li fid="u68d72d3a" data-lake-id="ufc655633" id="ufc655633"><span data-lake-id="uefa4161d" id="uefa4161d">索引上的等值查询，给唯一索引加锁的时候，next-key lock 退化为行锁。</span></li>
   <li fid="u68d72d3a" data-lake-id="u8fa6a717" id="u8fa6a717"><span data-lake-id="u52a4819e" id="u52a4819e">索引上的等值查询，向右遍历时且最后一个值不满足等值条件的时候，next-key lock 退化为间隙锁。</span></li>
  </ul>
  <p data-lake-id="uaca814c6" id="uaca814c6"><br></p>
  <p data-lake-id="u4f131b92" id="u4f131b92"><span data-lake-id="uc58f5901" id="uc58f5901">关于锁的介绍，就是这么多了，但是其实，RR的隔离级别引入的这些锁，虽然一定程度上可解决很多如幻读这样的问题，但是也会带来一些副作用，比如并发度降低、容易导致死锁等。</span></p>
  <p data-lake-id="uc038a66f" id="uc038a66f"><br></p>
  <p data-lake-id="uaa1cf391" id="uaa1cf391"><span data-lake-id="ubdd77d4c" id="ubdd77d4c">后面我们再来单独介绍一下为什么RR作为InnoDB的默认级别，却"不受待见"，很多大厂都会把数据库默认级别修改为RC。</span></p>
  <p data-lake-id="u027ffcfa" id="u027ffcfa"><br></p>
 </body>
</html>